package spring_learn.a02;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;

/**
 * beanFactory:
 * 1:不会主动调用beanFactory后处理器（添加更多的bean defination）
 * 2：不会主动调用bean后处理器（解析相应注解）
 * 3：不会主动初始化，是惰性的
 * 4：后处理器是有顺序的
 */
@SpringBootApplication
public class BeanFactoryTest {

    public static void main(String[] args) {
        DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
        //使用beanDefinition包装一个类的信息，类型，是否是单例，等等--
        AbstractBeanDefinition abd = BeanDefinitionBuilder.genericBeanDefinition(Config.class).
                setScope("singleton").getBeanDefinition();
        defaultListableBeanFactory.registerBeanDefinition("config",abd);

        //给beanfactory添加常见的后处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(defaultListableBeanFactory);
        //使后处理器生效，补充bean的定义
        defaultListableBeanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().
                forEach(beanFactoryPostProcessor ->beanFactoryPostProcessor.postProcessBeanFactory(defaultListableBeanFactory) );
        //如果没有上面后处理的作用，这里只能得到一个config类的defination
        //但是经过后处理器的作用，这里可以得到的denfination为：
        /**
         * config
         * org.springframework.context.annotation.internalConfigurationAnnotationProcessor
         * org.springframework.context.annotation.internalAutowiredAnnotationProcessor
         * org.springframework.context.annotation.internalCommonAnnotationProcessor
         * org.springframework.context.event.internalEventListenerProcessor
         * org.springframework.context.event.internalEventListenerFactory
         * bean1
         * bean2
         * bean3
         * bean4
         */
        String[] beanDefinitionNames = defaultListableBeanFactory.getBeanDefinitionNames();
        for (String name:beanDefinitionNames)
            System.out.println(name);
        //添加bean的处理器,针对bean的各个生命阶段进行拓展，例如解析autowried/resources注解
        defaultListableBeanFactory.getBeansOfType(BeanPostProcessor.class)
                .values()
                .stream().
                sorted(defaultListableBeanFactory.getDependencyComparator()).
                forEach(beanPostProcessor ->{
                    System.out.println(beanPostProcessor);
                    defaultListableBeanFactory.addBeanPostProcessor(beanPostProcessor);
                } );
        //准备好所有的bean
        defaultListableBeanFactory.preInstantiateSingletons();
        Bean1 bean1 = defaultListableBeanFactory.getBean(Bean1.class);
        System.out.println(bean1);
        //在没添加bean后处理器的时候，这两个get操作得到的都是null，代表注解没有被解析
        //而添加了bean后处理器后，对应的注解就会被解析，从而完成依赖注入
        System.out.println(bean1.getBean2());
        System.out.println(bean1.getInter());
        //这里得到的bean的种类，取决于使用了什么bean后处理器先进行处理
        //上面代码中如果去掉sorted(defaultListableBeanFactory.getDependencyComparator())，得到的就是bean3，加上之后就是bean4
        System.out.println(bean1.getInter().getClass());
    }



    //供上面进行测试的几个类
    @Configuration
    static class Config {
        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @Bean
        public Bean2 bean2() {
            return new Bean2();
        }

        @Bean
        public Bean3 bean3() {
            return new Bean3();
        }

        @Bean
        public Bean4 bean4() {
            return new Bean4();
        }
    }

    interface Inter {

    }

    static class Bean3 implements Inter {

    }

    static class Bean4 implements Inter {

    }

    static class Bean1 {
        private static final Logger log = LoggerFactory.getLogger(Bean1.class);

        public Bean1() {
            log.debug("构造 Bean1()");
        }

        @Autowired
        private Bean2 bean2;

        public Bean2 getBean2() {
            return bean2;
        }

        //实际生产中，这两个注解不会一起写
        @Autowired
        @Resource(name = "bean4")
        private Inter bean3;

        public Inter getInter() {
            return bean3;
        }
    }

    static class Bean2 {
        private static final Logger log = LoggerFactory.getLogger(Bean2.class);

        public Bean2() {
            log.debug("构造 Bean2()");
        }
    }
}
